OxyDex is the suite’s oxygen receptor — it senses one signal, blood-oxygen saturation, and reports it inward. From a raw overnight 1 Hz SpO₂/HR/motion trace it derives 75+ metrics, scores recovery readiness, and emits desaturation events onto the Ganglior bus.
Read the suite as a reflex arc: receptors → relay → integration → insight. OxyDex is an afferent receptor — it does exactly one transduction well and reports inward. It never reaches into another node; cross-signal work happens only through the Ganglior export, consumed by the Integrator.
OxyDex is built from external *.js files referenced by OxyDex.src.html and bundled to a standalone OxyDex.html. Dependencies point downhill only — UI → DSP → Core — and each file owns exactly one job. Edit the .js + .src.html, never the bundle; re-bundle after changes.
buildHash provenance stamp). 100% local.crossNight() stats stay per-node).tMs (local civil time encoded as if UTC) and reads it back with getUTC* — so the recording reads identically in any viewer’s timezone, and two devices recording the same minute land on the same tMs. parseTimestamp is duplicated locally by design.The pipeline is the same shape across the suite: ingest → parse on the canonical clock → compute in DSP → grade & render in UI → emit onto the bus. No number is computed in the render layer; it asks DSP for the value and the registry for how to show it.
Drag an O2Ring CSV (or summary/JSONL) onto the upload zone. Everything runs in-browser — nothing is uploaded.
Each row’s vendor timestamp is parsed by regex into a floating wall-clock tMs — never new Date(str) — so the night reads identically in any timezone.
Artifacts are masked, then the metric tiers are computed on the full cleaned series: SpO₂ stats, ODI-4, T90, hypoxic burden, pulse-HRV proxies, composites.
Render asks the registry for each metric’s depth tier and evidence grade, draws the readiness hero, KPI strip, SpO₂ trace and tables.
Export a ganglior.node-export JSON — desaturation events with wall-clock t — for the Integrator to fuse with other nodes.
Every metric OxyDex surfaces carries an evidence grade — a non-hue badge whose fill is the confidence ladder: solid bullseye for a raw reading, down to a dashed ring for a friendly estimate. A measurement and a projection must never look alike. Grades live in oxydex-registry.js, the one source of truth.
Honesty is architectural: a guess is never dressed as a measurement, a missing value stays null rather than fabricated, and confidence is kept separate from signal quality. The node-specific caveats:
OxyDex sees pulse rate at 1 Hz, not beat-to-beat RR. Its HRV-flavoured metrics are emerging, never validated — for real HRV magnitude it borrows an ECGDex/PulseDex export.
The cyclic-variation-of-heart-rate apnea signal flags pattern, not an AHI. It directs attention; it does not diagnose sleep apnea.
Finger/ring movement injects spurious dips. The cleaner masks the worst, and % analyzable is surfaced so a low-coverage night reads as low-confidence.
A missing timestamp stays null — never fabricated to “now”. Coverage gaps are visible rather than smoothed away.
OxyDex is one self-contained file. Open OxyDex.html in any browser — online, offline, or from file://. Nothing installs, nothing phones home.
Drag a O2Ring / Wellue / ViATOM export (raw 1 hz csv) onto the upload zone. It’s read in-browser and turned into metrics on your device alone.
Start in Core for the headline readiness and a plain-language line. Step up to Advanced for full tables and charts, or Research for composites and the full dump. Each metric’s evidence dot tells you how far to trust it.
Export a ganglior.node-export JSON to feed the Integrator, or to upgrade a peer node’s read. Events carry a wall-clock t; consumers reconstruct absolute time from the recording start.
Edit the oxydex-*.js files or OxyDex.src.html — never the bundled OxyDex.html — then re-bundle. Run Dex-Test-Suite.html until all-green, and verify-provenance.html after re-bundling.